﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xrm.Sdk;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;

namespace ADPasswordChange.Plugins
{
    public class ChangeADPwd : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
            // Obtain the execution context from the service provider.
            IPluginExecutionContext context = (IPluginExecutionContext)
            serviceProvider.GetService(typeof(IPluginExecutionContext));

            // The InputParameters collection contains all the data passed in the message request.
            if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity)
            {
                // Obtain the target entity from the input parmameters.
                Entity entity = (Entity)context.InputParameters["Target"];
                string dName = "";
                string ADomaine = "";
                string ADUser = "";
                // Plugin use this admin login/ password for changing the user and password
                // you must enter the value
                String AdminName = "Housni";
                String AdminPass = "Benhammou";

                if (entity.LogicalName == "new_passwordchange")
                {
                    // Check if password exists
                    try
                    {

                        IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                        IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
                        if (entity.Attributes.Contains("new_newpassword"))
                        {

                            string uPassword = entity.GetAttributeValue<String>("new_newpassword");
                            string oldPassword = entity.GetAttributeValue<string>("new_oldpassword");
                            string confirmPassword = entity.GetAttributeValue<string>("new_confirmnewpassword");
                            dName = entity.GetAttributeValue<string>("new_name");
                            // recupere le non de l'ad et l'utlisateur separement 
                            char[] splitters = new char[] { '\\' };
                            string[] ADUsers = dName.Split(splitters);
                            ADomaine = ADUsers[0];
                            ADUser = ADUsers[1];

                            //////////////////////////////////////////////////////////////////////
                            if (uPassword == confirmPassword)
                            {
                                PrincipalContext pc = new PrincipalContext(ContextType.Domain, ADomaine);
                                bool credentialsAreValid = pc.ValidateCredentials(ADUser, oldPassword);
                                if (credentialsAreValid)
                                {
                                    try
                                    {
                                        
                                        //Test
                                        DirectoryEntry Ldap = new DirectoryEntry("LDAP://" + ADomaine, AdminName, AdminPass, AuthenticationTypes.Secure);
                                        DirectorySearcher searcher = new DirectorySearcher(Ldap) { SearchRoot = Ldap, Filter = "(SAMAccountName=" + ADUser + ")" };
                                        SearchResult result = searcher.FindOne();
                                        DirectoryEntry DirEntry = result.GetDirectoryEntry();
                                        DirEntry.Invoke("SetPassword", new object[] { uPassword });
                                        DirEntry.CommitChanges();
                                        DirEntry.Close();

                                        //HttpContext.Current.Response.Write("<script type='text/javascript'>alert('" + AlerteMsg + "');</script>");


                                    }
                                    catch (Exception excep)
                                    {
                                        //H.Benhammou Vérifier si l'excepetion si c'est la politique du AD, afficher un exception personnalisée
                                        string Err2 = excep.ToString();
                                        if (Err2.Contains("The password does not meet the password policy requirements"))
                                        {
                                            throw new Exception("Error changing password.  <BR>Reason: <BR> "
                                                                 + "The password does not meet the following password policy requirements:<BR> <BR> "
                                                                 + "* 6 characters minimum.<BR> "
                                                                 + "* At least one Capital alphabet. <BR> "
                                                                 + "* At least one digits. <BR> "
                                                                 + "* Password should not contain the user's account name or parts of that name.");
                                        }
                                        else
                                        {
                                            throw new Exception("Error changing password.  <BR>Reason: <BR> " + excep.GetBaseException());
                                        }
                                    }

                                }
                                else
                                {
                                    throw new NullReferenceException("Error changing password.  <BR> Reason: <BR> Invalid old password, please try again <BR>");
                                }
                            }
                            else
                            {
                                throw new NullReferenceException("Error changing password. <BR> Reason: <BR> The new password and confirm password values do not match");

                            }



                            /////////////////////////////////////////////////////////////////////

                        }
                    }
                    catch (Exception ex)
                    {
                        tracingService.Trace("AD Reset plugin: {0}", ex.ToString());
                        throw;

                    }


                }
            }

        }
    }
}
